const faceapi = require('face-api.js');
const { Canvas, Image } = require('canvas');
const fs = require('fs');
const path = require('path');
const User = require('../models/user');

// 为face-api.js注册canvas
faceapi.env.monkeyPatch({ Canvas, Image });

class FaceRecognitionService {
  constructor() {
    this.isModelLoaded = false;
    this.labeledFaceDescriptors = [];
    this.lastDescriptorsUpdate = null;
    this.descriptorsCacheTimeout = 10 * 60 * 1000; // 5分钟缓存过期时间
  }

  async loadModels() {
    if (this.isModelLoaded) return;
    
    const modelsPath = path.join(__dirname, '../models');
    
    // 确保模型目录存在
    if (!fs.existsSync(modelsPath)) {
      fs.mkdirSync(modelsPath, { recursive: true });
    }
    
    // 加载更稳定的模型
    // 加载SSD MobileNet模型 - 更稳定的人脸检测
    await faceapi.nets.ssdMobilenetv1.loadFromDisk(modelsPath);
    // 加载68点面部特征点模型
    await faceapi.nets.faceLandmark68Net.loadFromDisk(modelsPath);
    // 加载人脸识别模型
    await faceapi.nets.faceRecognitionNet.loadFromDisk(modelsPath);
    
    this.isModelLoaded = true;
    console.log('Face recognition models loaded successfully');
  }

  async loadFaceDescriptors() {
    try {
      // 检查缓存是否有效
      const now = Date.now();
      if (this.lastDescriptorsUpdate && 
          (now - this.lastDescriptorsUpdate) < this.descriptorsCacheTimeout && 
          this.labeledFaceDescriptors.length > 0) {
        console.log('Using cached face descriptors');
        return;
      }

      const faceData = await User.getFaceDescriptors();
      
      this.labeledFaceDescriptors = faceData.map(face => {
        return new faceapi.LabeledFaceDescriptors(
          face.name,
          [new Float32Array(face.descriptor)]
        );
      });
      
      this.lastDescriptorsUpdate = now;
      console.log(`Loaded ${this.labeledFaceDescriptors.length} face descriptors`);
    } catch (error) {
      console.error('Error loading face descriptors:', error);
      throw error;
    }
  }

  async detectFace(imagePath) {
    await this.loadModels();
    
    try {
      // 加载图像
      const img = await this.loadImage(imagePath);
      
      // 使用SSD MobileNet进行人脸检测
      const detections = await faceapi.detectSingleFace(img)
        .withFaceLandmarks() // 使用68点面部特征点
        .withFaceDescriptor();
      
      if (!detections) {
        return { success: false, message: '未检测到人脸' };
      }
      
      return {
        success: true,
        descriptor: Array.from(detections.descriptor),
        detection: detections
      };
    } catch (error) {
      console.error('Error detecting face:', error);
      throw error;
    }
  }

  async recognizeFace(imagePath) {
    await this.loadModels();
    await this.loadFaceDescriptors();
    
    try {
      // 加载图像
      const img = await this.loadImage(imagePath);
      
      // 使用SSD MobileNet进行人脸检测
      const detection = await faceapi.detectSingleFace(img)
        .withFaceLandmarks() // 使用68点面部特征点
        .withFaceDescriptor();
      
      if (!detection) {
        return { success: false, message: '未检测到人脸' };
      }
      
      if (this.labeledFaceDescriptors.length === 0) {
        return { success: false, message: '数据库中没有人脸数据用于比对' };
      }
      
      // 创建人脸匹配器
      const faceMatcher = new faceapi.FaceMatcher(this.labeledFaceDescriptors, 0.4);
      // 进行匹配
      const match = faceMatcher.findBestMatch(detection.descriptor);
      
      return {
        success: true,
        match: {
          label: match.label=="unknown"?"没有识别到":match.label,
          distance: match.distance,
          isUnknown: match.label === 'unknown'
        }
      };
    } catch (error) {
      console.error('Error recognizing face:', error);
      throw error;
    }
  }

  async loadImage(imagePath) {
    const img = new Image();
    const buffer = fs.readFileSync(imagePath);
    return new Promise((resolve, reject) => {
      img.onload = () => resolve(img);
      img.onerror = (err) => {
        console.error('图像加载错误:', err);
        reject(err);
      };
      // 使用Buffer的toString方法将图像数据转换为base64格式
      img.src = 'data:image/jpeg;base64,' + buffer.toString('base64');
    });
  }

  async preprocessImage(imagePath) {
    // 加载图像
    const img = await this.loadImage(imagePath);
    
    // 创建canvas
    const canvas = new Canvas(img.width, img.height);
    const ctx = canvas.getContext('2d');
    
    // 绘制图像
    ctx.drawImage(img, 0, 0);
    
    // 应用图像处理（例如调整亮度、对比度）
    // 这里可以添加更多图像处理代码
    
    // 保存处理后的图像
    const processedImagePath = imagePath.replace(/\.\w+$/, '_processed$&');
    const out = fs.createWriteStream(processedImagePath);
    const stream = canvas.createJPEGStream({ quality: 0.95 });
    stream.pipe(out);
    
    return new Promise((resolve, reject) => {
      out.on('finish', () => resolve(processedImagePath));
      out.on('error', reject);
    });
  }
}

module.exports = new FaceRecognitionService();